package com.linzi.common.utils;

import java.net.InetAddress;
import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;

/**
 * @author chenmaolin
 * @version 1.0
 * @date 2021/11/9
 * @Description 获取mac地址
 */
@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
public class MacTools {
    /**
     * 因为一台机器不一定只有一个网卡呀，所以返回的是数组
     *
     * @return
     * @throws Exception
     */
    public static List<String> getMacList() throws Exception {
        Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces();
        StringBuilder sb = new StringBuilder();
        ArrayList<String> tmpMacList = new ArrayList<>();
        while (en.hasMoreElements()) {
            NetworkInterface iface = en.nextElement();
            List<InterfaceAddress> addrs = iface.getInterfaceAddresses();
            for (InterfaceAddress addr : addrs) {
                InetAddress ip = addr.getAddress();
                NetworkInterface network = NetworkInterface.getByInetAddress(ip);
                if (network == null) {
                    continue;
                }
                byte[] mac = network.getHardwareAddress();
                if (mac == null) {
                    continue;
                }
                sb.delete(0, sb.length());
                for (int i = 0; i < mac.length; i++) {
                    sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
                }
                tmpMacList.add(sb.toString());
            }
        }
        if (tmpMacList.size() <= 0) {
            return tmpMacList;
        }
        /***去重，别忘了同一个网卡的ipv4,ipv6得到的mac都是一样的，肯定有重复*/
        return tmpMacList.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 获取mac地址 返回一个
     *
     * @param ia
     * @return
     * @throws Exception
     */
    public static String getMACAddress(InetAddress ia) throws Exception {
        /**获得网络接口对象（即网卡），并得到mac地址，mac地址存在于一个byte数组中*/
        byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
        if (mac == null) {
            return null;
        }
        /**下面代码是把mac地址拼装成String*/
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < mac.length; i++) {
            if (i != 0) {
                sb.append("-");
            }
            /**mac[i] & 0xFF 是为了把byte转化为正整数*/
            String s = Integer.toHexString(mac[i] & 0xFF);
            sb.append(s.length() == 1 ? 0 + s : s);
        }
        /**把字符串所有小写字母改为大写成为正规的mac地址并返回*/
        return sb.toString().toUpperCase();
    }

    /**
     * 获取ip地址
     *
     * @return
     */
    public static InetAddress getLocalHostExactAddress() {
        try {
            InetAddress candidateAddress = null;
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface iface = networkInterfaces.nextElement();
                /**该网卡接口下的ip会有多个，也需要一个个的遍历，找到自己所需要的*/
                for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
                    InetAddress inetAddr = inetAddrs.nextElement();
                    /**排除loopback回环类型地址（不管是IPv4还是IPv6 只要是回环地址都会返回true）*/
                    if (!inetAddr.isLoopbackAddress()) {
                        if (inetAddr.isSiteLocalAddress()) {
                            /**如果是site-local地址，就是它了 就是我们要找的
                             *绝大部分情况下都会在此处返回你的ip地址值
                             * */
                            return inetAddr;
                        }
                        /**若不是site-local地址 那就记录下该地址当作候选*/
                        if (candidateAddress == null) {
                            candidateAddress = inetAddr;
                        }
                    }
                }
            }
            /**如果出去loopback回环地之外无其它地址了，那就回退到原始方案吧*/
            return candidateAddress == null ? InetAddress.getLocalHost() : candidateAddress;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取操作系统
     *
     * @return
     */
    public static String getOperSystem() {
        Properties props = System.getProperties();
        String property = props.getProperty("os.name");
        return property.toLowerCase();
    }

    /**
     * 获取系统版本
     *
     * @return
     */
    public static String getOperSystemVersion() {
        Properties props = System.getProperties();
        return props.getProperty("os.version").toLowerCase();
    }


    public static void main(String[] args) throws Exception {
        System.out.println("《====进行 address 测试===》");
        List<String> macList = getMacList();
        System.out.println("本机的mac网卡的地址有：" + macList);

        InetAddress ia = InetAddress.getLocalHost();
        System.out.println("获取当前使用的mac地址：" + getMACAddress(ia));

        System.out.println("获取当前的ip地址：" + getLocalHostExactAddress());

        System.out.println("操作系统的名称：" + getOperSystem());
        System.out.println("操作系统的版本号：" + getOperSystemVersion());

    }
}
